package cn.suchan.jianzhi.test;

/**
 * 知识点：异或运算
 * 问题描述：
 * 在一个数组中有0-99之间的整数101个(数组无序)，用高效方法找出其中的唯一的重复元素
 *
 * @author suchan
 * @date 2019/05/25
 */
public class XOR {

    /**
     * 根据异或运算的特性：相同为0，不同为1（0^0=0;0^1=1;1^0=1;1^1=0）
     * ①任何数与1做异或运算该数的二进制最低位取反（如：将1010 1110低4位取反，1010 1110^0000 1111=1010 0001）
     * ②任何数与0做异或运算该数的二进制位不变
     * ③任何数与几个数做偶数次的异或运算后还是该数（如：8^1^2^3^4^5^1^2^3^4^5=8）
     * <p>
     * 这道题就是用的第③个特性
     *
     * 用时：3ms
     *
     * @param arr
     * @return
     */
    public int find(int[] arr) {
        long start = System.currentTimeMillis();
        System.out.println("开始时间：" + start);
        int temp = arr[0];
        for (int i = 1; i < arr.length; i++) {
            temp = temp ^ arr[i];
        }
        // 之前是想直接跟数组的每个值进行两次异或运算，后来发现得到的总是0，而非重复的数字。
        // 因是因为本来得到了那个重复的数字，然后由于数组中那个数字是重复的，所以又跟自己做了一次异或运算，就是0了。
        // （如：5的二进制是0101,5^5=0101^0101=0）
        // 为保证第二次进行异或运算时不会出现重复的数字，就直接是这样子了
        for (int j = 0; j < arr.length - 1; j++) {
            temp = temp ^ j;
        }

        long end = System.currentTimeMillis();
        System.out.println("结束时间：" + end);
        /*long time = System.currentTimeMillis() - start;
        System.out.println("用时：" + time);*/
        return temp;
    }

    /**
     * 直接用循环判断，跟异或运算对比一下性能
     *
     * 用时：8ms
     *
     * @param arr
     * @return
     */
    public int find1(int[] arr) {
        long start = System.currentTimeMillis();
        System.out.println("开始时间：" + start);
        int result = 0;
        a:for (int i = 0; i < arr.length; i++) {
            b:for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] == arr[j]) {
                    result = arr[j];
                    break a;
                }
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("结束时间：" + end);
        /*long time = System.currentTimeMillis() - start;
        System.out.println("用时：" + time);*/
        return result;
    }

    public static void main(String[] args) {
        int arr[] = new int[101];
        for (int i = 0; i < arr.length - 1; i++) {
            arr[i] = i;
        }
        arr[100] = 5;

        XOR xor = new XOR();
        System.out.println("重复的数字是：" + xor.find1(arr));
        //System.out.println(5 ^ 1);
    }
}
